package org.example.util;

import org.example.bean.annotation.ExcelBean;
import org.example.bean.annotation.ExcelColumn;

import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * 本工具类依托自定义注解ExcelColumnName、ExcelBean实现对Bean对象的扫描以达成协助简化构建Excel导出工具类代码的目的
 * 本工具类会扫描指定的package，并根据targetName找出需要导出的Bean
 * 使用方法：
 * 1.创建导出Excel的Bean对象，并添加@ExcelBean(excelTitle = "xxxxx") 注解
 * 2.为对象的每个需要创建Excel列的参数添加@ExcelColumnName(columnName = "xxxx") 注解
 * 3.调用该方法传入@ExcelBean中的excelTitle
 *
 * @author gugu
 * @version 0.0.3
 * @since 2021/12/19 9:25
 */
public class ScanExcelBeanTool {
    /**
     *  ExcelBean注解中的 excelName
     */
    private final String excelTitle;

    private final Class<?> targetClass;

    public ScanExcelBeanTool(Class<?> targetClass){
        this.targetClass = targetClass;
        this.excelTitle = targetClass.getAnnotation(ExcelBean.class).excelTitle();
    }

    /**
     *  扫描目标类，找出指定bean类
     */
    public List<String> registerExcelColumnName(){
        List<String> paramList = new LinkedList<>();
        Field[] fields = targetClass.getDeclaredFields();
        ExcelBean excelBean = targetClass.getAnnotation(ExcelBean.class);
        // 检查是否有标记ExcelBean注解 并且为指定excelTitle
        if (null != excelBean && excelBean.excelTitle().equals(excelTitle)) {
            paramRegister(fields, paramList);
        }
        return paramList;
    }


    /**
     *  扫描目标类，找出指定bean类
     */
    public Map<Integer,String> registerExcelColumn(){
        Map<Integer,String> paramMap = new LinkedHashMap<>();
        Field[] fields = targetClass.getDeclaredFields();
        ExcelBean excelBean = targetClass.getAnnotation(ExcelBean.class);
        // 检查是否有标记ExcelBean注解 并且为指定excelTitle
        if (null != excelBean && excelBean.excelTitle().equals(excelTitle)) {
            paramRegisterByIndex(fields, paramMap);
        }
        return paramMap;
    }


    /**
     * 根据对象参数的ExcelColumnName注解，将注解中的columnName放入集合中
     * @param fields 参数类数组
     * @param paramList 返回的参数集合
     */
    public void paramRegister(Field[] fields, List<String> paramList) {
        for (Field field : fields) {
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            if (null == annotation) {
                return;
            }
            paramList.add(annotation.name());
        }
    }

    /**
     * 根据对象参数的ExcelColumnName注解，将注解中的columnName放入集合中
     * @param fields 参数类数组
     * @param map 返回的参数集合
     */
    public void paramRegisterByIndex(Field[] fields, Map<Integer,String> map) {
        for (Field field : fields) {
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            if (null == annotation) {
                return;
            }
            map.put(annotation.index(),annotation.name());
        }
        ObjectUtils.sortMapByKey(map);
    }

    /**
     * 扫描目标类，找出指定bean类
     */
    public List<String> registerExcelColumnNameByNameList(List<String> nameList){
        List<String> paramList = new LinkedList<>();
        Field[] fields = targetClass.getDeclaredFields();
        ExcelBean excelBean = targetClass.getAnnotation(ExcelBean.class);
        // 检查是否有标记ExcelBean注解 并且为指定excelTitle
        if (null != excelBean && excelBean.excelTitle().equals(excelTitle)) {
            paramRegisterByNameList(nameList ,fields, paramList);
        }
        return paramList;
    }

    /**
     * 根据对象参数的ExcelColumnName注解，将注解中的columnName放入集合中
     * @param fields 参数类数组
     * @param paramList 返回的参数集合
     */
    public void paramRegisterByNameList(List<String> nameList, Field[] fields, List<String> paramList) {
        for (Field field : fields) {
            ExcelColumn annotation = field.getAnnotation(ExcelColumn.class);
            if (null != annotation && nameList.contains(StringUtils.camel2UnderLine(field.getName()))) {
                paramList.add(annotation.name());
            }
        }
    }
}
